#include "Archer.h"
#include "DestroyGameObjectMessage.h"
#include "Game.h"
#include "AnimationSystem.h"
#include "GameplayState.h"
#include "Player.h"
#include "CreateBulletMessage.h"
#include "Projectile.h"
#include "../SGD Wrappers/SGD_AudioManager.h"
#include "TileSystem.h"

Archer::Archer()
{
	RegisterForEvent("KNIGHT_DIED");

	SetCurrAnimation("archerwalking");
	AnimationSystem::GetInstance()->StartPlaying(animInfo);
	AnimationSystem::GetInstance()->StartLooping(animInfo);

	m_hImage = SGD::GraphicsManager::GetInstance()->LoadTexture("resource/Graphics/archerTorso.png");
}

Archer::~Archer()
{
	SGD::GraphicsManager::GetInstance()->UnloadTexture(m_hImage);
}

void Archer::Update(float elapsedTime)
{
	Enemy::Update(elapsedTime);
	if (!updating) return;

	shootCooldown += elapsedTime;
	if (state == State::CLOSEIN) switchKnightooldown -= elapsedTime;

	if (m_ptPosition.x > GameplayState::GetInstance()->GetPlayer()->GetPosition().x)
		SetFacing(-1);
	if (m_ptPosition.x <= GameplayState::GetInstance()->GetPlayer()->GetPosition().x)
		SetFacing(1);
}

void Archer::Render()
{
	Enemy::Render();
	float rotation = RotationToPlayer();

	if (!animInfo.GetFlashOn())
	{
		if (facing > 0 && rotation < SGD::PI / 2 && rotation > -SGD::PI / 2)
			SGD::GraphicsManager::GetInstance()->DrawTexture(m_hImage, { GetWeaponOffset().x - 23 - Game::GetInstance()->GetCameraPos().x, GetWeaponOffset().y - 23 - Game::GetInstance()->GetCameraPos().y }, rotation, { 24, 22 });
		else if (facing < 0 && rotation < SGD::PI / 2 && rotation > -SGD::PI / 2)
			SGD::GraphicsManager::GetInstance()->DrawTexture(m_hImage, { GetWeaponOffset().x + 23 - Game::GetInstance()->GetCameraPos().x, GetWeaponOffset().y - 23 - Game::GetInstance()->GetCameraPos().y }, rotation, { 24, 22 }, {}, { -1.0f, 1.0f });
		else if (facing > 0)
			SGD::GraphicsManager::GetInstance()->DrawTexture(m_hImage, { GetWeaponOffset().x - 23 - Game::GetInstance()->GetCameraPos().x, GetWeaponOffset().y - 23 - Game::GetInstance()->GetCameraPos().y }, SGD::PI / 2, { 24, 22 });
		else if (facing < 0)
			SGD::GraphicsManager::GetInstance()->DrawTexture(m_hImage, { GetWeaponOffset().x + 23 - Game::GetInstance()->GetCameraPos().x, GetWeaponOffset().y - 23 - Game::GetInstance()->GetCameraPos().y }, -SGD::PI / 2, { 24, 22 }, {}, { -1.0f, 1.0f });
	}
	else if (animInfo.GetFlashOn())
	{
		if (facing > 0 && rotation < SGD::PI / 2 && rotation > -SGD::PI / 2)
			SGD::GraphicsManager::GetInstance()->DrawTexture(m_hImage, { GetWeaponOffset().x - 23 - Game::GetInstance()->GetCameraPos().x, GetWeaponOffset().y - 23 - Game::GetInstance()->GetCameraPos().y }, rotation, { 24, 22 }, { 255, 255, 0, 0 });
		else if (facing < 0 && rotation < SGD::PI / 2 && rotation > -SGD::PI / 2)
			SGD::GraphicsManager::GetInstance()->DrawTexture(m_hImage, { GetWeaponOffset().x + 23 - Game::GetInstance()->GetCameraPos().x, GetWeaponOffset().y - 23 - Game::GetInstance()->GetCameraPos().y }, rotation, { 24, 22 }, { 255, 255, 0, 0 }, { -1.0f, 1.0f });
		else if (facing > 0)
			SGD::GraphicsManager::GetInstance()->DrawTexture(m_hImage, { GetWeaponOffset().x - 23 - Game::GetInstance()->GetCameraPos().x, GetWeaponOffset().y - 23 - Game::GetInstance()->GetCameraPos().y }, SGD::PI / 2, { 24, 22 }, { 255, 255, 0, 0 });
		else if (facing < 0)
			SGD::GraphicsManager::GetInstance()->DrawTexture(m_hImage, { GetWeaponOffset().x + 23 - Game::GetInstance()->GetCameraPos().x, GetWeaponOffset().y - 23 - Game::GetInstance()->GetCameraPos().y }, -SGD::PI / 2, { 24, 22 }, { 255, 255, 0, 0 }, { -1.0f, 1.0f });
	}
}

/*virtual*/ bool Archer::DoAttack()
{
	return ((GameplayState::GetInstance()->GetPlayer()->GetPosition() - m_ptPosition).ComputeLength() < Game::GetInstance()->GetScreenWidth() / 3);
}

/*virtual*/ void Archer::Attack()
{
	GameplayState *gameplay = GameplayState::GetInstance();
	TileSystem* TS = TileSystem::GetInstance();
	SGD::Point playerPos = gameplay->GetPlayer()->GetPosition();

	//Shoot
	if (shootCooldown > 0.4f)
	{
		shootCooldown = 0.0f;
		CreateBulletMessage * Msg = new CreateBulletMessage{ this, RotationToPlayer(), false };
		Msg->QueueMessage();
	}

	//Get the nearest knight
	if (switchKnightooldown <= 0.0f)
	{
		switchKnightooldown = 1.5f;
		GetNearestKnight();
	}

	//Move behind knight
	if (knight)
	{
		if (knight->GetPosition().x < playerPos.x)
		{
			if (m_ptPosition.x > knight->GetPosition().x - 60.0f)
				MoveLeft();
		}
		else
		{
			if (m_ptPosition.x < knight->GetPosition().x + 60.0f)
				MoveRight();
		}
	}
	else
	{
		if (TS->CheckCollison(gameplay->GetMapIndex(), SGD::Point((m_ptPosition.x + 8) * facing, m_ptPosition.y + 8)))
			m_vtVelocity.x = -m_vtVelocity.x;
		//Move into attack range
		else if (abs(playerPos.x - m_ptPosition.x) > 200.0f)
			MoveTowardsPlayer();
		else
		{
			if (animInfo.GetCurrAnimation() != "archeridle")
				StartAnimation("archeridle");
		}
	}
}

void Archer::GetNearestKnight()
{
	GameplayState *gameplay = GameplayState::GetInstance();

	bool pickedOne = false;
	GameObject *temp;
	for (int i = 0; temp = gameplay->ReturnObject(ObjBuckets::ENEMY_BUCKET, i); i++)
	{
		if (temp->GetType() == ENEMY_KNIGHT)
		{
			if (!knight)
			{
				pickedOne = true;
				knight = (Knight *)temp;
			}
			else if ((knight->GetPosition() - m_ptPosition).ComputeLength() > (((Knight *)temp)->GetPosition() - m_ptPosition).ComputeLength())
			{
				//if shorter distance than curr target
				pickedOne = true;
				knight = (Knight *)temp;
			}
		}
	}

	if (!pickedOne) knight = nullptr;
}

/*virtual*/ void Archer::EnterIdle()
{
	if (state == State::IDLE) return;
	Enemy::EnterIdle();

	StartAnimation("archeridle");
}

/*virtual*/ void Archer::EnterPatrol()
{
	if (state == State::PATROL) return;
	Enemy::EnterPatrol();

	StartAnimation("archerwalking");
}

/*virtual*/ void Archer::EnterCloseIn()
{
	if (state == State::CLOSEIN) return;
	Enemy::EnterCloseIn();

	StartAnimation("archerwalking");
}

void Archer::MoveTowardsPlayer()
{
	GameplayState *gameplay = GameplayState::GetInstance();
	SGD::Point playerPos = gameplay->GetPlayer()->GetPosition();

	if (animInfo.GetCurrAnimation() == "goblinwalking")
	{
		StartAnimation("archerwalking");
	}

	//Move towards player
	if (playerPos.x < m_ptPosition.x)
		MoveLeft();
	else
		MoveRight();
}

void Archer::HandleCollision(GameObject* pOther)
{
	if (pOther->GetType() == MovingObject::OBJ_BULLET)
	{
		// don't shoot yourself
		if (((Projectile *)pOther)->GetOwner() == this) return;

		// call MovingObjects HandleCollision
		MovingObject::HandleCollision(pOther);
		// play hit sfx
		SGD::AudioManager::GetInstance()->PlayAudio(damageAudio);
	}

	CharacterCollision(pOther);
}

/*virtual*/ void Archer::HandleEvent(const SGD::Event* pEvent) /*override*/
{
	if (pEvent->GetEventID() == "KNIGHT_DIED")
	{
		if (pEvent->GetSender() == knight)
			knight = nullptr;
	}
	else
		MovingObject::HandleEvent(pEvent);
}
